﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SIAD.Model;
using SIAD.Controleur;
using System.ComponentModel;


// TODO Créer la liste des IA et l'instanciation par Réflection dans la factory
// TODO coder l'intéraction de jeu pour le joueur HUMAN
// TODO coder les statistiques
// TODO coder la commande undo
// TODO coder le chargement et la sauvegarde (rélféchir comment créer les joueurs et tout)
// TODO inclure les statistiques dans le chargement et la sauvegarde
// TODO faire les IA...
// TODO delegate ou backgroundworker pour la progress bar sur l'IA
namespace SIAD
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Constantes
        #endregion

        #region Property
        
        /// <summary>
        /// La partie
        /// </summary>
        private SIADGame theGame;

        /// <summary>
        /// Le joueur 1
        /// </summary>
        private Player playerOne;

        /// <summary>
        /// Le joueur 2
        /// </summary>
        private Player playerTwo;

        private Plateau thePlateau;

        #endregion

        #region Constructeur
        /// <summary>
        /// Constructeur de la fenêtre
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();            
        }
        #endregion       

        #region Private Methods
        /// <summary>
        /// Change la grille principale en grille de jeu
        /// </summary>
        private void setGame()
        {
            groupBoxConfiguration.Header = "Instruction";
            menuItemBack.IsEnabled = true;
            menuItemSave.IsEnabled = true;
            menuItemUndo.IsEnabled = true;
            menuItemLoad.IsEnabled = false;
            ButtonPlay.Visibility = System.Windows.Visibility.Hidden;
            sliderTaille.Visibility = System.Windows.Visibility.Hidden;
            textBoxPlateauSize.Visibility = System.Windows.Visibility.Hidden;
            labelInstruction.Visibility = System.Windows.Visibility.Visible;

        }

        /// <summary>
        /// Change la grille principale en grille de configuration
        /// </summary>
        private void setConfiguration()
        {
            groupBoxConfiguration.Header = "Configuration";
            menuItemBack.IsEnabled = false;
            menuItemSave.IsEnabled = false;
            menuItemUndo.IsEnabled = false;
            menuItemLoad.IsEnabled = true;
            ButtonPlay.Visibility = System.Windows.Visibility.Visible;
            sliderTaille.Visibility = System.Windows.Visibility.Visible;
            textBoxPlateauSize.Visibility = System.Windows.Visibility.Visible;
            labelInstruction.Visibility = System.Windows.Visibility.Hidden;
            setPlateauSize((int)sliderTaille.Value);
        }

        /// <summary>
        /// Change la taille du plateau
        /// </summary>
        /// <param name="tailleDuPlateau">La taille souhaité du plateau</param>
        private void setPlateauSize(int tailleDuPlateau)
        {
            // On ajoute 2 à la taille pour faire le contour
            thePlateau = new Plateau(tailleDuPlateau + 2);

            var aGrid = new Grid();

            for (int i = 0; i < tailleDuPlateau; i++)
            {
                var aColumnDefinition = new ColumnDefinition();
                aColumnDefinition.Width = new GridLength(2, GridUnitType.Star);

                var aRowDefinition = new RowDefinition();
                aRowDefinition.Height = new GridLength(2, GridUnitType.Star);
                aGrid.ColumnDefinitions.Add(aColumnDefinition);
                aGrid.RowDefinitions.Add(aRowDefinition);
            }

            for (int i = 0; i < tailleDuPlateau; i++)
            {
                for (int j = 0; j < tailleDuPlateau; j++)
                {
                    var aButton = new CaseBouton(thePlateau[i + 1, j + 1]);
                    aButton.SetValue(Grid.ColumnProperty, i);
                    aButton.SetValue(Grid.RowProperty, j);
                    aGrid.Children.Add(aButton);
                }
            }

            groupBoxPlateau.Content = aGrid;
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Gère le chargement de la fenêtre
        /// </summary>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            setConfiguration();

            playerOne = new Player("Player One", thePlateau, Common.CASE_TYPE.PLAYER_ONE);
            playerTwo = new Player("Player Two", thePlateau, Common.CASE_TYPE.PLAYER_TWO);

            // on s'abonne aux message de l'IA
            playerOne.MessageEvent += new Player.MessageEventHandler(player_MessageEvent);
            playerTwo.MessageEvent += new Player.MessageEventHandler(player_MessageEvent);

            theGame = new SIADGame(playerOne, playerTwo);

            comboBoxFirstPlayer.ItemsSource = IAStrategyFactory.getInstance().IATypeList;
            comboBoxFirstPlayer.Text = IAStrategyFactory.getInstance().IATypeList[0];
            comboBoxSecondPlayer.ItemsSource = IAStrategyFactory.getInstance().IATypeList;
            comboBoxSecondPlayer.Text = IAStrategyFactory.getInstance().IATypeList[0];
        }

        /// <summary>
        /// Reception des messages des joueurs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void player_MessageEvent(object sender, MessageEventArg e)
        {
            labelInstruction.Content = e.MessageText;
        }

        /// <summary>
        /// Gère un click sur le bouton Play (lance le plateau de jeu)
        /// </summary>
        private void buttonPlay_Click(object sender, RoutedEventArgs e)
        {
            setGame();
            theGame.playOneGame();
        }

        /// <summary>
        /// Gère le changement de valeur du slider qui gère la taille du plateau
        /// </summary>
        private void sliderTaille_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (groupBoxPlateau != null)
            {
                setPlateauSize((int)e.NewValue);
            }
        }

        /// <summary>
        /// Gère le retour à l'écran de configuration
        /// </summary>
        private void BackMenuItem_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("You really want to go back to the Configuration screen ?", "Back to Configuration", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                setConfiguration();
                theGame.stopGame();
            }            
        }

        /// <summary>
        /// Gère la fin de l'application
        /// </summary>
        private void QuitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Gestion du changement de type d'IA pour le joueur 2
        /// </summary>
        private void comboBoxSecondPlayer_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            String theIA = comboBoxSecondPlayer.SelectedValue as String;
            playerOne.theStrategy = IAStrategyFactory.getInstance().createStrategy(theIA, thePlateau, Common.CASE_TYPE.PLAYER_TWO);
        }

        /// <summary>
        /// Gestion du changement de type d'IA pour le joueur 1
        /// </summary>
        private void comboBoxFirstPlayer_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            String theIA = comboBoxSecondPlayer.SelectedValue as String;
            playerTwo.theStrategy = IAStrategyFactory.getInstance().createStrategy(theIA, thePlateau, Common.CASE_TYPE.PLAYER_ONE);
        }

        #region Command handler

        /// <summary>
        /// Gère le chargement d'une partie
        /// </summary
        private void LoadMenuItem_Click(object sender, RoutedEventArgs e)
        {

        }

        /// <summary>
        /// Gère la sauvegarde d'une partie
        /// </summary>
        private void SaveMenuItem_Click(object sender, RoutedEventArgs e)
        {

        }

        /// <summary>
        /// Appel la commande Undo
        /// </summary>
        private void UndoMenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        #endregion                
        #endregion
    }
}
